#include "codekata_statistics.h"
#include <stdio.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif

#define MAX_STAT_HANDLE_NUM 128

typedef struct {
    StatHandleWithName handlePool[MAX_STAT_HANDLE_NUM];
    int                statUseEnd;
} StatController;

StatController g_statCtrl = {0};

BEST_STATUS StatInit(StatHandle *handle, StatName name)
{
    if (g_statCtrl.statUseEnd >= MAX_STAT_HANDLE_NUM) {
        printf("exceed use...\n");
        return BEST_ERR;
    }
    StatHandleWithName *handleWithName =
        &g_statCtrl.handlePool[g_statCtrl.statUseEnd];
    if (handleWithName->haveUse) {
        return BEST_ERR;
    }

    if (name.name[0] == 0) {
        printf("no invalid name\n");
    } else {
        (void)memcpy(handleWithName->name.name, name.name, 32);
    }
    handleWithName->haveUse = 1;
    handleWithName->handle  = g_statCtrl.statUseEnd;
    *handle                 = handleWithName->handle;

    return BEST_OK;
}

int statGetHandleWithName(StatHandle           handle,
                          StatHandleWithName **inHandleWithName)
{
    if (handle >= MAX_STAT_HANDLE_NUM) {
        return 1;
    }
    StatHandleWithName *handleWithName = &g_statCtrl.handlePool[handle];
    if (!handleWithName->haveUse) {
        return 1;
    }
    *inHandleWithName = handleWithName;
    return 0;
}

BEST_STATUS StatAdd(StatHandle handle, int cnt)
{
    StatHandleWithName *handleWithName = NULL;
    int                 ret = statGetHandleWithName(handle, &handleWithName);
    if (ret != 0) {
        return ret;
    }
    handleWithName->cnt++;
    return 0;
}

BEST_STATUS StatGet(StatHandle handle, int *cnt)
{
    StatHandleWithName *handleWithName = NULL;
    int                 ret = statGetHandleWithName(handle, &handleWithName);
    if (ret != 0) {
        return ret;
    }
    *cnt = handleWithName->cnt;
    return 0;
}

BEST_STATUS StatEcho(StatHandle handle, StatEchoFunc fn)
{
    StatHandleWithName *handleWithName = NULL;

    if (statGetHandleWithName(handle, &handleWithName) != 0) {
        return BEST_ERR;
    }
    fn(handleWithName->name, handleWithName->cnt);
    return 0;
}

BEST_STATUS StatEchoAll(StatEchoFunc fn)
{
    int i;

    StatHandleWithName *handleWithName = NULL;
    for (i = 0; i < MAX_STAT_HANDLE_NUM; i++) {
        handleWithName = &g_statCtrl.handlePool[i];
        if (!handleWithName->haveUse) {
            continue;
        }

        fn(handleWithName->name, handleWithName->cnt);
    }

    return 0;
}

#ifdef __cplusplus
}
#endif